import Client, {
    AbortAndRollbackChangeOrderRequest,
    AbortAndRollbackChangeOrderResponse,
    AbortChangeOrderRequest,
    AbortChangeOrderResponse,
    ConfirmPipelineBatchRequest,
    ConfirmPipelineBatchResponse,
    DeployApplicationRequest,
    DeployApplicationResponse,
    DescribeApplicationConfigRequest,
    DescribeApplicationConfigResponse,
    DescribeChangeOrderRequest,
    DescribeChangeOrderResponse,
    DescribeChangeOrderResponseBodyData
} from '@alicloud/sae20190506'
import process from 'process'
import OpenApi, * as $OpenApi from '@alicloud/openapi-client';
import * as step from '@flow-step/step-toolkit'



export interface SaeInterface{
    describeApplicationConfig(request: DescribeApplicationConfigRequest): Promise<DescribeApplicationConfigResponse>
    deployApplication(request: DeployApplicationRequest): Promise<DeployApplicationResponse>
    describeChangeOrder(request: DescribeChangeOrderRequest): Promise<DescribeChangeOrderResponse>
    confirmPipelineBatch(request: ConfirmPipelineBatchRequest): Promise<ConfirmPipelineBatchResponse>
    abortChangeOrder(request: AbortChangeOrderRequest): Promise<AbortChangeOrderResponse>
    abortAndRollbackChangeOrder(request: AbortAndRollbackChangeOrderRequest): Promise<AbortAndRollbackChangeOrderResponse>
    getNextPipelineID(changeOrderDetail: DescribeChangeOrderResponseBodyData): Promise<string | undefined>
}

export class Sae implements SaeInterface{
    private readonly client: Client

    constructor(client: Client) {
        this.client = client
    }

    async describeApplicationConfig(request: DescribeApplicationConfigRequest): Promise<DescribeApplicationConfigResponse> {
        return this.client.describeApplicationConfig(request)
    }

    async deployApplication(request: DeployApplicationRequest): Promise<DeployApplicationResponse> {
        return this.client.deployApplication(request)
    }

    async describeChangeOrder(request: DescribeChangeOrderRequest): Promise<DescribeChangeOrderResponse> {
        return this.client.describeChangeOrder(request)
    }

    async confirmPipelineBatch(request: ConfirmPipelineBatchRequest): Promise<ConfirmPipelineBatchResponse> {
        return this.client.confirmPipelineBatch(request)
    }

    async abortChangeOrder(request: AbortChangeOrderRequest): Promise<AbortChangeOrderResponse> {
        return this.client.abortChangeOrder(request)
    }

    async abortAndRollbackChangeOrder(request: AbortAndRollbackChangeOrderRequest): Promise<AbortAndRollbackChangeOrderResponse> {
        return this.client.abortAndRollbackChangeOrder(request)
    }

     async getNextPipelineID(changeOrderDetail: DescribeChangeOrderResponseBodyData) {
        if (changeOrderDetail.status != 8){
            return Promise.resolve(undefined)
        }
        // @ts-ignore
        for (let pipeline of  changeOrderDetail.pipelines) {
            if (pipeline.status == 0)
                return Promise.resolve(pipeline.pipelineId)
        }
        return Promise.resolve(undefined)
    }
}

export async function getSAEClient() {
    if (process.env.SAE_ACCESS_KEY_ID == undefined){
        step.info(`Getting SAE Certificate`)
        const certificate = await getSAECertificate()
        step.exportEnvVar("SAE_ACCESS_KEY_ID", certificate.accessKeyId)
        step.exportEnvVar("SAE_ACCESS_KEY_SECRET", certificate.accessKeySecret)
        step.exportEnvVar("SAE_SECURITY_TOKEN", certificate.securityToken)
    }

    step.addOutput(`SAE_ACCESS_KEY_ID=${process.env.SAE_ACCESS_KEY_ID}`)
    step.addOutput(`SAE_ACCESS_KEY_SECRET=${process.env.SAE_ACCESS_KEY_SECRET}`)
    step.addOutput(`SAE_SECURITY_TOKEN=${process.env.SAE_SECURITY_TOKEN}`)

    let config = new $OpenApi.Config({
        accessKeyId: process.env.SAE_ACCESS_KEY_ID,
        accessKeySecret: process.env.SAE_ACCESS_KEY_SECRET,
        securityToken: process.env.SAE_SECURITY_TOKEN,
    });
    config.endpoint = `sae.${process.env.REGION_ID}.aliyuncs.com`;

    return Promise.resolve(new Client(config));
}

export async function getSAECertificate(){
    const flowJobToken: string | undefined =
        process.env['FLOW_JOB_TOKEN']
    if (flowJobToken == undefined) {
        throw new Error('missing FLOW_JOB_TOKEN')
    }
    const certificate = await step.certificate.getRamStsCertificate(flowJobToken,process.env.SERVICE_CONNECTION_ID as string)

    if (certificate === undefined || certificate.accessKeyId === "") {
        throw new Error(`get RamStsCertificate but error: ${JSON.stringify(certificate)}`)
    }
    step.debug(`get RamStsCertificate data: ${JSON.stringify(certificate)}`)

    return Promise.resolve(certificate)
}






